home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / Xconq 7.0d37 / source / x11 / ximf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-04  |  10.2 KB  |  404 lines  |  [TEXT/KAHL]

  1. /* X11-specific functions for image families in Xconq.
  2.    Copyright (C) 1992, 1993, 1994, 1995 Stanley T. Shebs.
  3.  
  4. Xconq is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.  See the file COPYING.  */
  8.  
  9. #include "config.h"
  10. #include "misc.h"
  11. #include "lisp.h"
  12. #include "imf.h"
  13. extern int smallest_image PROTO ((ImageFamily *imf, int *wp, int *hp));
  14.  
  15. #include <X11/Xos.h>
  16. #include <X11/Xlib.h>
  17. #include <X11/Xutil.h>
  18. #include <X11/Xresource.h>
  19.  
  20. #include "ximf.h"
  21.  
  22. extern char *imflib;
  23.  
  24. static Pixmap x11_load_bitmap PROTO ((Display *dpy, Window rootwin,
  25.                       char *name, char *ext, int *w, int *h));
  26. static void x11_make_color_pixmap PROTO ((Display *dpy, Window rootwin,
  27.                       Image *img));
  28.  
  29. X11Image *
  30. init_x11_image(img)
  31. Image *img;
  32. {
  33.     X11Image *ximg;
  34.  
  35.     ximg = (X11Image *) xmalloc(sizeof(X11Image));
  36.     ximg->mono = None;
  37.     ximg->mask = None;
  38.     /* Point to the generic image. */
  39.     ximg->generic = img;
  40.     ximg->colpix = NULL;
  41.     return ximg;
  42. }
  43.  
  44. X11Image *
  45. get_x11_image(img)
  46. Image *img;
  47. {
  48.     X11Image *ximg;
  49.  
  50.     if (img->hook)
  51.       return (X11Image *) img->hook;
  52.     ximg = init_x11_image(img);
  53.     img->hook = (char *) ximg;
  54.     return ximg;
  55. }
  56.  
  57. /* This tries to fill in the given image family by looking for and loading
  58.    standard X11 bitmap files. */
  59.  
  60. void
  61. x11_load_imf(dpy, rootwin, imf)
  62. Display *dpy;
  63. Window rootwin;
  64. ImageFamily *imf;
  65. {
  66.     int w, h;
  67.     Pixmap pic;
  68.     Image *img;
  69.     X11Image *ximg;
  70.  
  71.     /* If no imf or no name, don't even try. */
  72.     if (imf == NULL || imf->name == NULL)
  73.       return;
  74.     if (strcmp(imf->name, "none") == 0)
  75.       return;
  76.     if (0 /* found an imf file */) {
  77.     } else {
  78.     img = NULL;
  79.     ximg = NULL;
  80.     /* Just grab up plausibly-named bitmaps. */
  81.     pic = x11_load_bitmap(dpy, rootwin, imf->name, "b", &w, &h);
  82.     if (pic != None) {
  83.         img = get_img(imf, w, h);
  84.         ximg = get_x11_image(img);
  85.         ximg->mono = pic;
  86.     }
  87.     pic = x11_load_bitmap(dpy, rootwin, imf->name, "m", &w, &h);
  88.     if (pic != None) {
  89.         img = get_img(imf, w, h);
  90.         ximg = get_x11_image(img);
  91.         ximg->mask = pic;
  92.     }
  93.     pic = x11_load_bitmap(dpy, rootwin, imf->name, "8.b", &w, &h);
  94.     if (pic != None) {
  95.         img = get_img(imf, w, h);
  96.         ximg = get_x11_image(img);
  97.         ximg->mono = pic;
  98.     }
  99.     pic = x11_load_bitmap(dpy, rootwin, imf->name, "8.m", &w, &h);
  100.     if (pic != None) {
  101.         img = get_img(imf, w, h);
  102.         ximg = get_x11_image(img);
  103.         ximg->mask = pic;
  104.     }
  105.     pic = x11_load_bitmap(dpy, rootwin, imf->name, "32.b", &w, &h);
  106.     if (pic != None) {
  107.         img = get_img(imf, w, h);
  108.         ximg = get_x11_image(img);
  109.         ximg->mono = pic;
  110.     }
  111.     pic = x11_load_bitmap(dpy, rootwin, imf->name, "32.m", &w, &h);
  112.     if (pic != None) {
  113.         img = get_img(imf, w, h);
  114.         ximg = get_x11_image(img);
  115.         ximg->mask = pic;
  116.     }
  117. #if 0
  118.     if (imf->numsizes == 0) {
  119.         /* (should not complain unless no colors either -
  120.            check mac rules) */
  121.         fprintf(stderr,
  122.             "Image named \"%s\" not found here or in \"%s\"!\n",
  123.             imf->name, imflib);
  124.     }
  125. #endif
  126.     if (img && ximg)
  127.       img->hook = (char *) ximg;
  128.     }
  129. }
  130.  
  131. /* Try to load a bitmap of the given name, looking in both the current dir
  132.    and the library dir.  Warns about failure, but returns None, so the rest
  133.    of the code will continue to function. */
  134.  
  135. static Pixmap
  136. x11_load_bitmap(dpy, rootwin, name, ext, wp, hp)
  137. Display *dpy;
  138. Window rootwin;
  139. char *name, *ext;
  140. int *wp, *hp;
  141. {
  142.     int hotx, hoty;
  143.     unsigned int w, h;
  144.     Pixmap rslt;
  145.     static char sbuf[1000];
  146.  
  147.     if (ext != NULL) {
  148.     make_pathname(NULL, name, ext, sbuf);
  149.     if (XReadBitmapFile(dpy, rootwin, sbuf,
  150.                 &w, &h, &rslt, &hotx, &hoty) == BitmapSuccess) {
  151.         DGprintf("Loaded bitmap \"%s\"\n", sbuf);
  152.         *wp = w;  *hp = h;
  153.         return rslt;
  154.     }
  155.     make_pathname(imflib, name, ext, sbuf);
  156.     if (XReadBitmapFile(dpy, rootwin, sbuf,
  157.                 &w, &h, &rslt, &hotx, &hoty) == BitmapSuccess) {
  158.         DGprintf("Loaded bitmap \"%s\"\n", sbuf);
  159.         *wp = w;  *hp = h;
  160.         return rslt;
  161.     }
  162.     }
  163.     return None;
  164. }
  165.  
  166. /* if (force): prefer data over rawdata; always re-create pixmaps */
  167.  
  168. void
  169. x11_interp_imf(dpy, rootwin, imf, force)
  170. Display *dpy;
  171. Window rootwin;
  172. ImageFamily *imf;
  173. int force;
  174. {
  175.     int w, h, rowbytes, numbytes;
  176.     Image *img;
  177.     X11Image *ximg;
  178.  
  179.     for (img = imf->images; img != NULL; img = img->next) {
  180.     w = img->w;  h = img->h;
  181.     ximg = get_x11_image(img);
  182.     if (img->monodata != lispnil && (img->rawmonodata == NULL || force)) {
  183.         rowbytes = (w + 7) / 8;
  184.         numbytes = h * rowbytes;
  185.         img->rawmonodata = xmalloc(numbytes);
  186.         interp_bytes(img->monodata, numbytes, img->rawmonodata, 0);
  187.         reverse_bit_endianness(img->rawmonodata, numbytes);
  188.     }
  189.     if (img->rawmonodata && (ximg->mono == None || force)) {
  190.         ximg->mono =
  191.           XCreateBitmapFromData(dpy, rootwin, img->rawmonodata, w, h);
  192.     }
  193.     if (img->maskdata != lispnil && (img->rawmaskdata == NULL || force)) {
  194.         rowbytes = (w + 7) / 8;
  195.         numbytes = h * rowbytes;
  196.         img->rawmaskdata = xmalloc(numbytes);
  197.         interp_bytes(img->maskdata, numbytes, img->rawmaskdata, 0);
  198.         reverse_bit_endianness(img->rawmaskdata, numbytes);
  199.     }
  200.     if (img->rawmaskdata && (ximg->mask == None || force)) {
  201.         ximg->mask =
  202.           XCreateBitmapFromData(dpy, rootwin, img->rawmaskdata, w, h);
  203.     }
  204.     if (img->colrdata != lispnil && (img->rawcolrdata == NULL || force)) {
  205.         rowbytes = (w * img->pixelsize + 7) / 8;
  206.         numbytes = h * rowbytes;
  207.         img->rawcolrdata = xmalloc(numbytes);
  208.         interp_bytes(img->colrdata, numbytes, img->rawcolrdata, 0);
  209.     }
  210.     if (img->rawcolrdata && (ximg->colr == None || force)) {
  211.         x11_make_color_pixmap(dpy, rootwin, img);
  212.     }
  213.     }
  214. }
  215.  
  216. /* X11 bitmaps are always in little-endian bit order, while IMF images
  217.    are always big-endian in bit order, so we must reverse the bits
  218.    in each byte individually. */
  219.  
  220. void
  221. reverse_bit_endianness(rawdata, numbytes)
  222. char *rawdata;
  223. int numbytes;
  224. {
  225.     int i, j, byte, byte2;
  226.  
  227.     for (i = 0; i < numbytes; ++i) {
  228.     byte = rawdata[i];
  229.     byte2 = 0;
  230.     for (j = 0; j < 8; ++j) {
  231.         byte2 = (byte2 << 1) | (byte & 1);
  232.         byte >>= 1;
  233.     }
  234.     rawdata[i] = byte2;
  235.     }
  236. }
  237.  
  238. static void
  239. x11_make_color_pixmap(dpy, rootwin, img)
  240. Display *dpy;
  241. Window rootwin;
  242. Image *img;
  243. {
  244.     unsigned short ipal[4][256];
  245.     Pixel idx[256], pixel;
  246.     int r, ri, rc, depth, c, ln, screen, rsize;
  247.     int rowbytesize, bytesize, rmask;
  248.     XColor col;
  249.     char buf[BUFSIZE], *dp, *rp, *data;
  250.     Obj *pal, *color;
  251.     Colormap cmap;
  252.     Pixmap pixmap;
  253.     XImage *ximage;
  254.     GC gc;
  255.     X11Image *ximg = (X11Image *) img->hook;
  256.  
  257.     if (ximg == NULL || img->palette == lispnil || img->rawcolrdata == NULL)
  258.       return;
  259.     /* Can't make color pixmaps if we don't have any colors. */
  260.     if (img->palette == lispnil && img->rawpalette == NULL)
  261.       return;
  262.  
  263.     if (!img->rawpalette) {
  264.     /* Parse the palette. */
  265.     c = 0;
  266.     for (pal = img->palette; pal != lispnil; pal = cdr(pal)) {
  267.         color = car(pal);
  268.         ipal[0][c] = c_number(car(color));
  269.         ipal[1][c] = c_number(car(cdr(color)));
  270.         ipal[2][c] = c_number(car(cdr(cdr(color))));
  271.         ipal[3][c] = c_number(car(cdr(cdr(cdr(color)))));
  272.         c++;
  273.     }
  274.     img->numcolors = c;
  275.     if (c == 0)
  276.       return;
  277.   
  278.     /* store palette */
  279.     img->rawpalette = (int *) xmalloc(img->numcolors * 4 * sizeof(int));
  280.     for (c = 0; c < img->numcolors; c++) {
  281.         for (ln = 0; ln < 4; ln++) {
  282.         img->rawpalette[4 * c + ln] = ipal[ln][c];
  283.         }
  284.     }
  285.     }
  286.  
  287.     screen = DefaultScreen(dpy);
  288.     cmap = XDefaultColormap(dpy, screen);
  289.     depth = DefaultDepth(dpy, screen);
  290.     if (depth % 8)
  291.       return;
  292.  
  293.     if (img->numcolors <= 0) {
  294.     run_warning("No colors?");
  295.     return;
  296.     }
  297.  
  298.     /* allocate colors */
  299.     ximg->colpix = (Pixel *) xmalloc(img->numcolors * sizeof(Pixel));
  300.     for (c = 0; c < img->numcolors; c++) {
  301.     col.red   = img->rawpalette[4 * c + 1];
  302.     col.green = img->rawpalette[4 * c + 2];
  303.     col.blue  = img->rawpalette[4 * c + 3];
  304.     col.flags = DoRed | DoGreen | DoBlue;
  305.     if (XAllocColor(dpy, cmap, &col)) {
  306.         ximg->colpix[c] = col.pixel;
  307.     } else {
  308.         sprintf(buf, "%2.2x%2.2x%2.2x",
  309.             img->rawpalette[4*c+1],
  310.             img->rawpalette[4*c+2],
  311.             img->rawpalette[4*c+3]);
  312.         init_warning("Cannot alloc color #%s, will leave black", buf);
  313.         ximg->colpix[c] = XBlackPixel(dpy,screen);
  314.     }
  315.     }
  316.  
  317.     /* find reverse index->pixel mapping */
  318.     for (c = 0; c < 256; c++) {
  319.     idx[c] = XBlackPixel(dpy, screen);
  320.     }
  321.     for (c = 0; c < img->numcolors; c++) {
  322.     idx[img->rawpalette[4 * c + 0]] = ximg->colpix[c];
  323.     }
  324.  
  325.     /* make color data */
  326.     rsize = img->pixelsize;
  327.     rmask = (1 << img->pixelsize) - 1;
  328.     rowbytesize = img->w * depth / 8;
  329.     bytesize = rowbytesize * img->h;
  330.     data = xmalloc(bytesize * sizeof(char));
  331.     dp = data;
  332.     rp = img->rawcolrdata;
  333.     for (r = 0; r < img->h; r++) {
  334.     ri = 8 - img->pixelsize;
  335.     for (c = 0; c < img->w; c++) {
  336.         rc = ((int) (*rp >> ri)) & rmask;
  337.         if (ri) {
  338.         ri -= img->pixelsize;
  339.         } else {
  340.         ri = 8 - img->pixelsize;
  341.         rp++;
  342.         }
  343.         pixel = idx[rc];
  344.         for (ln = depth - 8; ln >= 0; ln -= 8) {
  345.         *dp = (pixel >> ln) & 0xff;
  346.         dp++;
  347.         }
  348.     }
  349.     if ((img->pixelsize * img->w) % 8) {
  350.         rp++;
  351.     }
  352.     }
  353.  
  354.     /* convert to XImage */
  355.     ximage = XCreateImage(dpy, DefaultVisual(dpy, screen), depth,
  356.               ZPixmap, 0, data, img->w, img->h,
  357.               8, rowbytesize);
  358.     if (!ximage) {
  359.     free(data);
  360.     return;
  361.     }
  362.     ximage->byte_order = MSBFirst;
  363.     ximage->bitmap_bit_order = MSBFirst;
  364.     
  365.     /* and finally to Pixmap */
  366.     pixmap = XCreatePixmap(dpy, rootwin, img->w, img->h, depth);
  367.     if (!pixmap)
  368.       pixmap = None;
  369.     if (pixmap == None) {
  370.     XDestroyImage(ximage);
  371.     /* XDestroyImage also frees data */
  372.     return;
  373.     }
  374.     gc = XCreateGC(dpy, pixmap, 0, NULL);
  375.     XPutImage(dpy, pixmap, gc, ximage, 0, 0, 0, 0,
  376.           ximage->width, ximage->height);
  377.     XFreeGC(dpy, gc);
  378.     XDestroyImage(ximage);
  379.     /* XDestroyImage also frees data */
  380.  
  381.     ximg->colr = pixmap;
  382. }
  383.  
  384. /* (should be a generic routine) */
  385. int
  386. smallest_image(imf, wp, hp)
  387. ImageFamily *imf;
  388. int *wp, *hp;
  389. {
  390.     Image *img, *smallest = NULL;
  391.  
  392.     if (imf == NULL)
  393.       return FALSE;
  394.     for (img = imf->images; img != NULL; img = img->next) {
  395.     if (smallest == NULL || (img->w < smallest->w && img->h < smallest->h))
  396.       smallest = img;
  397.     }
  398.     if (smallest != NULL) {
  399.     *wp = smallest->w;  *hp = smallest->h;
  400.     return TRUE;
  401.     }
  402.     return FALSE;
  403. }
  404.